﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CarbonExchange.Bll;

namespace CarbonExchange.Tests
{
    [TestClass]
    public class ContentNodeTests : BaseTest
    {
        private void ValidateProperties(ContentNode node, Dal.ContentNode dalNode, Dal.ContentNodePosition dalPosition)
        {
            Assert.AreEqual(dalNode.Id, node.Id);
            Assert.AreEqual(dalNode.CreatedDateTime.ToLocalTime(), node.CreatedDateTime);
            Assert.AreEqual(dalPosition.PublishDate.HasValue ? new DateTime?(dalNode.PublishFrom.Value.ToLocalTime()) : null, node.CurrentVersion);
            Assert.AreEqual(dalNode.DeveloperLocked, node.DeveloperLocked);
            Assert.AreEqual(dalNode.DisplayName, node.DisplayName);
            Assert.AreEqual(dalNode.Name, node.Name);
            Assert.AreEqual(dalNode.NodeGuid, node.NodeGuid);
            Assert.AreEqual(dalNode.Notes, node.Notes);
            Assert.AreEqual(dalPosition.ParentNodeGuid, node.ParentGuid);
            Assert.AreEqual(dalPosition.ParentPath, node.ParentPath);
            Assert.AreEqual(dalNode.PublishFrom.HasValue ? new DateTime?(dalNode.PublishFrom.Value.ToLocalTime()) : null, node.PublishFrom);
            Assert.AreEqual(dalNode.PublishTo.HasValue ? new DateTime?(dalNode.PublishTo.Value.ToLocalTime()) : null, node.PublishTo);
            Assert.AreEqual(dalNode.ReadyToPublish, node.ReadyToPublish);
            Assert.AreEqual(dalNode.RequiresPublishing, node.RequiresPublishing);
            Assert.AreEqual(dalPosition.Sequence, node.Sequence);
            Assert.AreEqual(dalNode.SiteId, node.SiteId);
            Assert.AreEqual(dalNode.Site.Name, node.SiteName);
            Assert.AreEqual(dalNode.Summary, node.Summary);
            Assert.AreEqual(dalNode.TemplateId, node.TemplateId);
            Assert.AreEqual(dalNode.Template.Name, node.TemplateName);
            Assert.AreEqual(string.Format("{0}{1}", dalPosition.ParentPath, dalNode.Name), node.Path);

            string queryString = null;
            if (dalPosition.PublishDate == null)
            {
                queryString = "?AcmsSV=Pending";
            }
            else
            {
                var latestVersion = _TestContentNodePositions.Where(x => x.ContentNode.NodeGuid == dalNode.NodeGuid && x.PublishDate <= DateTime.UtcNow).OrderByDescending(x => x.PublishDate).First().PublishDate.Value;
                if (dalPosition.PublishDate.Value != latestVersion)
                {
                    queryString = string.Concat("?AcmsSV=", System.Web.HttpUtility.UrlEncode(dalPosition.PublishDate.Value.ToServerTime().ToString("yyyy/MM/dd HH:mm"))); ;
                }
            }
            Assert.AreEqual(string.Format("{0}{1}.aspx{2}", dalPosition.ParentPath, dalNode.Name == "~" ? "~/default" : dalNode.Name, queryString), node.Url);
        }

        private void ValidateProperties(ContentNode a, ContentNode b)
        {
            Assert.IsNotNull(a);
            Assert.IsNotNull(b);
            Assert.AreEqual(a.Id, b.Id);
            Assert.AreEqual(a.CreatedDateTime, b.CreatedDateTime);
            Assert.AreEqual(a.CurrentVersion, b.CurrentVersion);
            Assert.AreEqual(a.DeveloperLocked, b.DeveloperLocked);
            Assert.AreEqual(a.DisplayName, b.DisplayName);
            Assert.AreEqual(a.Name, b.Name);
            Assert.AreEqual(a.NodeGuid, b.NodeGuid);
            Assert.AreEqual(a.Notes, b.Notes);
            Assert.AreEqual(a.ParentGuid, b.ParentGuid);
            Assert.AreEqual(a.ParentPath, b.ParentPath);
            Assert.AreEqual(a.ParentSequence, b.ParentSequence);
            Assert.AreEqual(a.Path, b.Path);
            Assert.AreEqual(a.PublishFrom, b.PublishFrom);
            Assert.AreEqual(a.PublishTo, b.PublishTo);
            Assert.AreEqual(a.ReadyToPublish, b.ReadyToPublish);
            Assert.AreEqual(a.RequiresPublishing, b.RequiresPublishing);
            Assert.AreEqual(a.Sequence, b.Sequence);
            Assert.AreEqual(a.SiteId, b.SiteId);
            Assert.AreEqual(a.SiteName, b.SiteName);
            Assert.AreEqual(a.Summary, b.Summary);
            Assert.AreEqual(a.TemplateId, b.TemplateId);
            Assert.AreEqual(a.TemplateName, b.TemplateName);
            Assert.AreEqual(a.Url, b.Url);
        }


        [TestMethod]
        public void ContentNode_GetById_WithIncorrectId_ReturnsNull()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetById(int.MaxValue);
            Assert.IsNull(tmp);
        }

        [TestMethod]
        public void ContentNode_GetById_WithCorrectId_ReturnsNull()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetById(_TestContentNodes[1].Id);
            Assert.IsNotNull(tmp);
        }

        [TestMethod]
        public void ContentNode_GetById_PopulatesCorrectly()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetById(_TestContentNodes[1].Id);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, _TestContentNodes[1], _TestContentNodes[1].ContentNodePositions[0]);
        }

        [TestMethod]
        public void ContentNode_GetById_ForNodeWithMulplePositionRecords_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).First();
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.Where(x => x.PublishDate < DateTime.UtcNow).OrderByDescending(x => x.PublishDate.Value).First();

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetById(tmpNode.Id);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetById_WithVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).First();
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.Where(x => x.PublishDate < DateTime.UtcNow).OrderByDescending(x => x.PublishDate.Value).First();
            DateTime version = DateTime.Now;

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetById(tmpNode.Id, version);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetById_WithNullVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes[0];
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.First();
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetById(tmpNode.Id, null);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetByGuid_WithVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).First();
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.Where(x => x.PublishDate < DateTime.UtcNow).OrderByDescending(x => x.PublishDate.Value).First();
            DateTime version = DateTime.Now;

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetByNodeGuid(tmpNode.NodeGuid, version);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetByGuid_WithNullVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes[1];
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.First();

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetByNodeGuid(tmpNode.NodeGuid, null);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetBySiteIdAndPath_WithVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).First();
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.Where(x=> x.PublishDate < DateTime.UtcNow).OrderByDescending(x => x.PublishDate.Value).First();
            DateTime version = DateTime.Now;

            string path = string.Format("{0}{1}", tmpPosition.ParentPath ?? "", tmpNode.Name);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetBySiteIdAndPath(_TestSite.Id, path, version);

            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetBySiteIdAndPath_WithTrailingSlash_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).First();
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.Where(x => x.PublishDate < DateTime.UtcNow).OrderByDescending(x => x.PublishDate.Value).First();
            DateTime version = DateTime.Now;

            string path = string.Format("{0}{1}/", tmpPosition.ParentPath ?? "", tmpNode.Name);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetBySiteIdAndPath(_TestSite.Id, path, version);

            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetBySiteIdAndPath_WithNullVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes[1];
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions[0];

            string path = string.Format("{0}{1}", tmpPosition.ParentPath ?? "", tmpNode.Name);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetBySiteIdAndPath(_TestSite.Id, path, null);

            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetBySiteUrlAndPath_WithVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).First();
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions.Where(x => x.PublishDate < DateTime.UtcNow).OrderByDescending(x => x.PublishDate.Value).First();
            DateTime version = DateTime.Now;

            string siteRoot = _TestSite.SiteRoots[0].Url;
            string path = string.Format("{0}{1}", tmpPosition.ParentPath ?? "", tmpNode.Name);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetBySiteUrlAndPath(siteRoot, path, version);

            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetBySiteUrlAndPath_WithNullVersion_PopulatesCorrectly()
        {
            Dal.ContentNode tmpNode = _TestContentNodes[1];
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions[0];

            string siteRoot = _TestSite.SiteRoots[0].Url;
            string path = string.Format("{0}{1}", tmpPosition.ParentPath ?? "", tmpNode.Name);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetBySiteUrlAndPath(siteRoot, path, null);

            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, tmpNode, tmpPosition);
        }

        [TestMethod]
        public void ContentNode_GetBySiteUrlAndPath_WithInvalidSiteId_ReturnsNull()
        {
            Dal.ContentNode tmpNode = _TestContentNodes[1];
            Dal.ContentNodePosition tmpPosition = tmpNode.ContentNodePositions[0];

            string siteRoot = "rubbish";
            string path = string.Format("{0}{1}", tmpPosition.ParentPath ?? "", tmpNode.Name);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetBySiteUrlAndPath(siteRoot, path, null);

            Assert.IsNull(tmp);
        }

        [TestMethod]
        public void ContentNode_GetAllByParentGuid_WithInvalidGuid_ReturnsNull()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetAllByParentGuid(Guid.NewGuid(), null).ToList();
            Assert.AreEqual(0, tmp.Count());
        
            tmp = factory.GetAllByParentGuid(Guid.NewGuid(), _TestContentNodePositions.Where(x => x.PublishDate.HasValue).OrderByDescending(x => x.PublishDate).First().PublishDate).ToList();
            Assert.AreEqual(0, tmp.Count());
        }

        [TestMethod]
        public void ContentNode_GetAllByParentGuid_WithNullVersion_PopulatesListCorrectly()
        {
            Guid guid = _TestContentNodes[0].NodeGuid;

            var tmpNodePositions = _TestContentNodePositions.Where(x => x.ParentNodeGuid == guid && !x.PublishDate.HasValue);
            var tmpNodes = _TestContentNodes.Where(x=> tmpNodePositions.Select(y => y.ContentNode.Id).Contains(x.Id));

            Assert.AreEqual(tmpNodePositions.Count(), tmpNodes.Count());
            
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmpList = factory.GetAllByParentGuid(guid, null).ToList();

            Assert.IsTrue(tmpList.Count() > 0);

            Assert.AreEqual(tmpNodes.Count(), tmpList.Count());
            
            var i = 0;
            foreach (var tmp in tmpList)
            {
                ValidateProperties(tmp, tmpNodes.ElementAt(i), tmpNodePositions.ElementAt(i));
                i++;
            }
        }

        [TestMethod]
        public void ContentNode_GetAllByParentGuid_WithVersion_PopulatesListCorrectly()
        {
            Guid guid = _TestContentNodes[0].NodeGuid;
            var version = _TestContentNodePositions.Where(x => x.PublishDate != null && x.PublishDate.Value <= DateTime.UtcNow && x.ParentNodeGuid == guid).Select(x => x.PublishDate.Value).Max().ToLocalTime();
            
            var tmpNodePositions = _TestContentNodePositions.Where(x => x.ParentNodeGuid == guid && x.PublishDate == version.ToUniversalTime());
            var tmpNodes = _TestContentNodes.Where(x => tmpNodePositions.Select(y => y.ContentNode.Id).Contains(x.Id));

            Assert.AreEqual(tmpNodePositions.Count(), tmpNodes.Count());

            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmpList = factory.GetAllByParentGuid(guid, version).ToList();

            Assert.IsTrue(tmpList.Count() > 0);

            Assert.AreEqual(tmpNodes.Count(), tmpList.Count());

            var i = 0;
            foreach (var tmp in tmpList)
            {
                ValidateProperties(tmp, tmpNodes.ElementAt(i), tmpNodePositions.ElementAt(i));
                i++;
            }
        }

        [TestMethod]
        public void ContentNode_GetAllByParentGuid_WithVersion_PopulatesListCorrectly1()
        {
            var guids = _TestContentNodes.GroupBy(x => x.NodeGuid).Select(x => x.Key);;
            DateTime version = DateTime.Now;
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            foreach (var guid in guids)
            {
                var tmp1 = _TestContentNodePositions.Where(x => x.ParentNodeGuid == guid && (x.PublishDate ?? DateTime.MaxValue) < version);
                var tmp2 = tmp1.GroupBy(x => x.PublishDate);
                var tmp3 = tmp2.OrderByDescending(x => x.Key);
                var tmp = tmp3.FirstOrDefault();

                int expected = tmp == null ? 0 : tmp.Count();
                Assert.AreEqual(expected, factory.GetAllByParentGuid(guid, version).ToList().Count());
            }
        }

        [TestMethod]
        public void ContentNode_GetAllBySiteIdAndParentPath_WithInvalidSiteId_ReturnsEmptyList()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            Assert.AreEqual(0, factory.GetAllBySiteIdAndParentPath(int.MaxValue, "~", null).ToList().Count());
            Assert.AreEqual(0, factory.GetAllBySiteIdAndParentPath(int.MaxValue, "~", DateTime.Now).ToList().Count());
        }

        [TestMethod]
        public void ContentNode_GetAllBySiteIdAndParentPath_WithInvalidPath_ReturnsEmptyList()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            Assert.AreEqual(0, factory.GetAllBySiteIdAndParentPath(_TestSite.Id, "~/rubbish", null).ToList().Count());
            Assert.AreEqual(0, factory.GetAllBySiteIdAndParentPath(_TestSite.Id, "~/rubbish", DateTime.Now).ToList().Count());
        }

        [TestMethod]
        public void ContentNode_GetAllBySiteIdAndParentPath_WithNullVersion_ReturnsPopulatedList()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            Assert.AreEqual(2, factory.GetAllBySiteIdAndParentPath(_TestSite.Id, "~", null).ToList().Count());

            string path = string.Concat("~/", _TestContentNodes[1].Name);

            Assert.AreEqual(3, factory.GetAllBySiteIdAndParentPath(_TestSite.Id, path, null).ToList().Count());
        }

        [TestMethod]
        public void ContentNode_GetAllBySiteIdAndParentPath_WithVersion_ReturnsPopulatedList()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmpList = factory.GetAllBySiteIdAndParentPath(_TestSite.Id, "~", DateTime.Now).ToList();
            Assert.AreEqual(2, tmpList.Count);
            foreach (var tmp in tmpList)
            {
                int index = 1;
                if (tmpList.IndexOf(tmp) == 1)
                {
                    index = 2;
                }
                var tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[index].NodeGuid && x.Id != _TestContentNodes[index].Id).First();
                var tmpNodePosition = tmpNode.ContentNodePositions.Where(x => (x.PublishDate ?? DateTime.MaxValue) < DateTime.UtcNow).OrderByDescending(x => x.PublishDate).First();
                ValidateProperties(tmp, tmpNode, tmpNodePosition);
            }
        }

        [TestMethod]
        public void ContentNode_GetTopLevel_WithNullVersion_ReturnsPopulatedItem()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmp = factory.GetTopLevelBySiteId(_TestSite.Id, null);
            Assert.IsNotNull(tmp);
            ValidateProperties(tmp, _TestContentNodes[0], _TestContentNodes[0].ContentNodePositions[0]);
        }

        [TestMethod]
        public void ContentNode_GetTopLevel_WithNotNullVersion_ReturnsPopulatedItem()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[0].NodeGuid && x.Id != _TestContentNodes[0].Id).First();
            var tmpNodePosition = tmpNode.ContentNodePositions.OrderByDescending(x => x.PublishDate).First();

            var tmp = factory.GetTopLevelBySiteId(_TestSite.Id, DateTime.Now);
            Assert.IsNotNull(tmp);

            ValidateProperties(tmp, tmpNode, tmpNodePosition);
        }

        [TestMethod]
        public void ContentNode_GetTopLevel_WithIncorrectSiteId_ReturnsNull()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmp = factory.GetTopLevelBySiteId(int.MaxValue, DateTime.Now);
            Assert.IsNull(tmp);
        }

        [TestMethod]
        public void ContentNode_GetCurrentVersions_WithIncorrectGuid_ReturnsEmptyList()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetCurrentVersions(Guid.NewGuid());
            Assert.AreEqual(0, tmp.Count());
        }

        [TestMethod]
        public void ContentNode_GetCurrentVersions_WithCorrectGuid_ReturnsPopulatedList()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetCurrentVersions(_TestContentNodes[1].NodeGuid).ToList();
            Assert.AreEqual(2, tmp.Count());
            Assert.IsNull(tmp[0].PublishFrom);
            Assert.IsNotNull(tmp[1].PublishFrom);

            ValidateProperties(tmp[0], _TestContentNodes[1], _TestContentNodes[1].ContentNodePositions[0]);

            var secondNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).OrderByDescending(x => x.PublishFrom).First();
            var secondPosition = secondNode.ContentNodePositions.OrderBy(x => x.PublishDate).First();
            ValidateProperties(tmp[1], secondNode, secondPosition);
        }

        [TestMethod]
        public void ContentNode_GetAllVersions_WithCorrectGuid_ReturnsPopulatedList()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var tmp = factory.GetAllVersions(_TestContentNodes[1].NodeGuid).ToList();
            Assert.AreEqual(4, tmp.Count());
            Assert.IsNull(tmp[0].PublishFrom);
            Assert.IsNotNull(tmp[1].PublishFrom);
            Assert.IsTrue(tmp[1].PublishFrom > tmp[2].PublishFrom);
            Assert.IsNotNull(tmp[2].PublishFrom);
            Assert.IsTrue(tmp[2].PublishFrom > tmp[3].PublishFrom);
            Assert.IsNotNull(tmp[3].PublishFrom);

            ValidateProperties(tmp[0], _TestContentNodes[1], _TestContentNodes[1].ContentNodePositions[0]);

            for (int i = 1; i < tmp.Count; i++)
            {
                var tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).OrderByDescending(x => x.PublishFrom).Skip(i - 1).First();
                var tmpPosition = tmpNode.ContentNodePositions.OrderBy(x => x.PublishDate).First();

                ValidateProperties(tmp[i], tmpNode, tmpPosition);
            }
        }

        [TestMethod]
        public void ContentNode_ChildrenTest()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var homePage = factory.GetTopLevelBySiteId(_TestSite.Id, null);
            Assert.IsNotNull(homePage);
            Assert.AreEqual(2, homePage.Children.Count());
            Assert.AreEqual(3, homePage.Children.ToList()[0].Children.Count());
            Assert.AreEqual(0, homePage.Children.ToList()[1].Children.Count());

            homePage = factory.GetTopLevelBySiteId(_TestSite.Id, DateTime.Now);
            Assert.IsNotNull(homePage);
            Assert.AreEqual(2, homePage.Children.Count());
            Assert.AreEqual(0, homePage.Children.ToList()[0].Children.Count());
            Assert.AreEqual(0, homePage.Children.ToList()[1].Children.Count());
        }

        [TestMethod]
        public void ContentNode_FindChildByNameTest()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var homePage = factory.GetTopLevelBySiteId(_TestSite.Id, null);

            Assert.IsNotNull(homePage);
            
            var child = homePage.FindChildByName(_TestContentNodes[2].Name);

            Assert.IsNotNull(child);
            ValidateProperties(child, _TestContentNodes[2], _TestContentNodes[2].ContentNodePositions[0]);

            homePage = factory.GetTopLevelBySiteId(_TestSite.Id, DateTime.Now);

            Assert.IsNotNull(homePage);
            var tmpNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[2].NodeGuid && x != _TestContentNodes[2]).First();
            child = homePage.FindChildByName(tmpNode.Name);

            Assert.IsNotNull(child);
            ValidateProperties(child, tmpNode, tmpNode.ContentNodePositions.OrderByDescending(x => x.PublishDate).First());
        }

        [TestMethod]
        public void ContentNode_GetDefaultFileTest()
        {
            var dalTemplateFile = _TestContentNodes[0].Template.TemplateFiles.Where(x => x.IsDefault).SingleOrDefault();
            Assert.IsNotNull(dalTemplateFile);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var homePage = factory.GetTopLevelBySiteId(_TestSite.Id, null);
            Assert.IsNotNull(homePage);

            var templateFile = homePage.GetDefaultFile();
            Assert.IsNotNull(templateFile);
            Assert.AreEqual(dalTemplateFile.Id, templateFile.Id);
        }

        [TestMethod]
        public void ContentNode_GetFileTest()
        {
            var dalTemplateFile = _TestContentNodes[0].Template.TemplateFiles.Where(x => !x.IsDefault).FirstOrDefault();
            Assert.IsNotNull(dalTemplateFile);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var homePage = factory.GetTopLevelBySiteId(_TestSite.Id, null);
            Assert.IsNotNull(homePage);
            
            var templateFile = homePage.GetFile(dalTemplateFile.Name);
            Assert.IsNotNull(templateFile);
            Assert.AreEqual(dalTemplateFile.Id, templateFile.Id);
        }

        [TestMethod]
        public void ContentNode_UrlPendingTest()
        {
            var tmpDalNode = _TestContentNodes[0];
            var tmpDalPosition = tmpDalNode.ContentNodePositions[0];

            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmp = factory.GetById(tmpDalNode.Id, null);
            Assert.IsNotNull(tmp);
            Assert.AreEqual("~/default.aspx?AcmsSV=Pending", tmp.Url);
        }

        [TestMethod]
        public void ContentNode_UrlCurrentTest()
        {
            var tmpDalNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[0].NodeGuid && x.Id != _TestContentNodes[0].Id).First();
            var tmpDalPosition = tmpDalNode.ContentNodePositions[0];

            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmp = factory.GetById(tmpDalNode.Id, tmpDalPosition.PublishDate.Value.ToLocalTime());
            Assert.IsNotNull(tmp);
            Assert.AreEqual("~/default.aspx", tmp.Url);
        }

        [TestMethod]
        public void ContentNode_UrlNotCurrentTest()
        {
            var tmpDalNode = _TestContentNodes.Where(x => x.NodeGuid == _TestContentNodes[1].NodeGuid && x.Id != _TestContentNodes[1].Id).ElementAt(1);
            var tmpDalPosition = tmpDalNode.ContentNodePositions.OrderByDescending(x => x.PublishDate).ElementAt(0);

            ContentNodeFactory factory = new ContentNodeFactory(_Context);

            var tmp = factory.GetById(tmpDalNode.Id, tmpDalPosition.PublishDate.Value.ToLocalTime());
            Assert.IsNotNull(tmp);
            string expectedUrl = string.Format("{0}{1}.aspx?AcmsSV={2}", tmpDalPosition.ParentPath, tmpDalNode.Name, System.Web.HttpUtility.UrlEncode(tmpDalPosition.PublishDate.Value.ToServerTime().ToString("yyyy/MM/dd hh:mm")));
            Assert.AreEqual(expectedUrl, tmp.Url);
        }

        [TestMethod]
        public void ContentNode_CreateHomePageTest()
        {
            var factory = new ContentNodeFactory(_Context);
            var homePage = factory.CreateItem(_AlternateSite.Id);
            homePage.TemplateId = _TestTemplates[0].Id;
            homePage.DisplayName = "Welcome";
            homePage.Notes = "This is the Home Page";
            homePage.Summary = "This is the summary";

            DateTime expected = DateTime.Now;
            factory.Save(homePage);

            Assert.IsTrue(homePage.Id > 0);
            Assert.IsTrue(homePage.CreatedDateTime - expected < TimeSpan.FromSeconds(1));
            Assert.AreEqual(null, homePage.CurrentVersion);
            Assert.AreEqual(false, homePage.DeveloperLocked);
            Assert.AreEqual("Welcome", homePage.DisplayName);
            Assert.AreEqual("~", homePage.Name);
            Assert.AreNotEqual(Guid.Empty, homePage.NodeGuid);
            Assert.AreEqual("This is the Home Page", homePage.Notes);
            Assert.AreEqual(null, homePage.ParentGuid);
            Assert.AreEqual(null, homePage.ParentPath);
            Assert.AreEqual(null, homePage.ParentSequence);
            Assert.AreEqual("~", homePage.Path);
            Assert.AreEqual(null, homePage.PublishFrom);
            Assert.AreEqual(null, homePage.PublishTo);
            Assert.AreEqual(false, homePage.ReadyToPublish);
            Assert.AreEqual(true, homePage.RequiresPublishing);
            Assert.AreEqual(0, homePage.Sequence);
            Assert.AreEqual(_AlternateSite.Id, homePage.SiteId);
            Assert.AreEqual(_AlternateSite.Name, homePage.SiteName);
            Assert.AreEqual("This is the summary", homePage.Summary);
            Assert.AreEqual(_TestTemplates[0].Id, homePage.TemplateId);
            Assert.AreEqual(_TestTemplates[0].Name, homePage.TemplateName);
            Assert.AreEqual("~/default.aspx?AcmsSV=Pending", homePage.Url);

            var tmp = factory.GetByNodeGuid(homePage.NodeGuid, null);

            ValidateProperties(tmp, homePage);
        }

        [TestMethod]
        [ExpectedException(typeof(Bll.Exceptions.ValidationException))]
        public void ContentNode_InsertSecondHomePage_ThrowsValidationException()
        {
            var factory = new ContentNodeFactory(_Context);
            var homePage = factory.CreateItem(_TestSite.Id);
            homePage.TemplateId = _TestTemplates[0].Id;
            homePage.DisplayName = "Welcome";
            homePage.Notes = "This is the Home Page";
            homePage.Summary = "This is the summary";

            factory.Save(homePage);
        }

        [TestMethod]
        public void ContentNode_InsertChildPost()
        {
            var factory = new ContentNodeFactory(_Context);
            var homePage = factory.GetTopLevelBySiteId(_TestSite.Id, null);

            var tmp = factory.CreateItem(_TestSite.Id);
            tmp.TemplateId = _TestTemplates[0].Id;
            tmp.Name = "NewTest";
            tmp.DisplayName = "New Test";
            tmp.Notes = "This is the New Page";
            tmp.Summary = "This is the summary";
            tmp.ParentGuid = homePage.NodeGuid;
            tmp.DeveloperLocked = true;

            DateTime expected = DateTime.Now;
            factory.Save(tmp);

            Assert.IsTrue(tmp.Id > 0);
            Assert.IsTrue(tmp.CreatedDateTime - expected < TimeSpan.FromSeconds(1));
            Assert.AreEqual(null, tmp.CurrentVersion);
            Assert.AreEqual(true, tmp.DeveloperLocked);
            Assert.AreEqual("New Test", tmp.DisplayName);
            Assert.AreEqual("NewTest", tmp.Name);
            Assert.AreNotEqual(Guid.Empty, tmp.NodeGuid);
            Assert.AreEqual("This is the New Page", tmp.Notes);
            Assert.AreEqual(homePage.NodeGuid, tmp.ParentGuid);
            Assert.AreEqual("~/", tmp.ParentPath);
            Assert.AreEqual("0", tmp.ParentSequence);
            Assert.AreEqual("~/NewTest", tmp.Path);
            Assert.AreEqual(null, tmp.PublishFrom);
            Assert.AreEqual(null, tmp.PublishTo);
            Assert.AreEqual(false, tmp.ReadyToPublish);
            Assert.AreEqual(true, tmp.RequiresPublishing);
            Assert.AreEqual(2, tmp.Sequence);
            Assert.AreEqual(_TestSite.Id, tmp.SiteId);
            Assert.AreEqual(_TestSite.Name, tmp.SiteName);
            Assert.AreEqual("This is the summary", tmp.Summary);
            Assert.AreEqual(_TestTemplates[0].Id, tmp.TemplateId);
            Assert.AreEqual(_TestTemplates[0].Name, tmp.TemplateName);
            Assert.AreEqual("~/NewTest.aspx?AcmsSV=Pending", tmp.Url);

            var tmp2 = factory.GetByNodeGuid(tmp.NodeGuid, null);

            ValidateProperties(tmp2, tmp);

            var tmpList = factory.GetAllByParentGuid(homePage.NodeGuid, null).ToList();

            Assert.AreEqual(3, tmpList.Count());
            ValidateProperties(tmpList[2], tmp); 
        }



        [TestMethod]
        public void ContentNode_PublishSingleHomePageTest()
        {
            var factory = new ContentNodeFactory(_Context);

            var homePage = factory.CreateItem(_AlternateSite.Id);
            homePage.TemplateId = _TestTemplates[0].Id;
            homePage.DisplayName = "Welcome";
            homePage.Notes = "This is the Home Page";
            homePage.Summary = "This is the summary";

            factory.Save(homePage);

            Assert.AreNotEqual(0, homePage.Id);
            Assert.AreNotEqual(Guid.Empty, homePage.NodeGuid);

            DateTime expected = DateTime.Now;
            factory.Publish(homePage);

            //check that the publish from date
            Assert.IsNotNull(homePage.PublishFrom);
            Assert.IsTrue(homePage.PublishFrom - expected < TimeSpan.FromSeconds(1) );

            expected = homePage.PublishFrom.Value;

            Assert.AreEqual(expected, homePage.CurrentVersion);
            Assert.AreEqual(null, homePage.ParentPath);
            Assert.AreEqual(null, homePage.ParentSequence);

            var tmpList = factory.GetAllVersions(homePage.NodeGuid).ToList();

            Assert.AreEqual(2, tmpList.Count());
            ValidateProperties(tmpList[1], homePage);
            Assert.AreNotEqual(tmpList[0].Id, homePage.Id);

            Assert.AreEqual(expected, tmpList[0].CreatedDateTime);
            Assert.AreEqual(null, tmpList[0].CurrentVersion);
            Assert.AreEqual(homePage.DeveloperLocked, tmpList[0].DeveloperLocked);
            Assert.AreEqual(homePage.DisplayName, tmpList[0].DisplayName);
            Assert.AreEqual(homePage.Name, tmpList[0].Name);
            Assert.AreEqual(homePage.NodeGuid, tmpList[0].NodeGuid);
            Assert.AreEqual(homePage.Notes, tmpList[0].Notes);
            Assert.AreEqual(homePage.ParentGuid, tmpList[0].ParentGuid);
            Assert.AreEqual(homePage.ParentPath, tmpList[0].ParentPath);
            Assert.AreEqual(homePage.ParentSequence, tmpList[0].ParentSequence);
            Assert.AreEqual(homePage.Path, tmpList[0].Path);
            Assert.AreEqual(null, tmpList[0].PublishFrom);
            Assert.AreEqual(null, tmpList[0].PublishTo);
            Assert.AreEqual(false, tmpList[0].ReadyToPublish);
            Assert.AreEqual(false, tmpList[0].RequiresPublishing);
            Assert.AreEqual(homePage.Sequence, tmpList[0].Sequence);
            Assert.AreEqual(homePage.SiteId, tmpList[0].SiteId);
            Assert.AreEqual(homePage.SiteName, tmpList[0].SiteName);
            Assert.AreEqual(homePage.Summary, tmpList[0].Summary);
            Assert.AreEqual(homePage.TemplateId, tmpList[0].TemplateId);
            Assert.AreEqual(homePage.TemplateName, tmpList[0].TemplateName);
            Assert.AreEqual(string.Concat(homePage.Url, "?AcmsSV=Pending"), tmpList[0].Url);
        }

        [TestMethod]
        public void ContentNode_PublishHomePageTest()
        {
            ContentNodeFactory factory = new ContentNodeFactory();
            var tmp = factory.GetTopLevelBySiteId(_TestSite.Id, null);
            Assert.IsNotNull(tmp);

            var existing = factory.GetAllVersions(tmp.NodeGuid).Count();

            DateTime expected = DateTime.Now;
            factory.Publish(tmp);

            Assert.IsNotNull(tmp.CurrentVersion);
            Assert.IsTrue( tmp.CurrentVersion.Value - expected < TimeSpan.FromSeconds(1));
            Assert.AreEqual(tmp.CurrentVersion, tmp.PublishFrom);
            Assert.IsNull(tmp.PublishTo);

            var tmpList = factory.GetAllVersions(tmp.NodeGuid).ToArray();
            Assert.AreEqual(existing + 1, tmpList.Count());

            ValidateProperties(tmp, tmpList[1]);
        }

        [TestMethod]
        public void ContentNode_ChildPageTest()
        {
            ContentNodeFactory factory = new ContentNodeFactory();
            var tmp = factory.GetByNodeGuid(_TestContentNodes[1].NodeGuid, null);
            Assert.IsNotNull(tmp);

            var existing = factory.GetAllVersions(tmp.NodeGuid).Count();

            DateTime expected = DateTime.Now;
            
            factory.Publish(tmp);

            Assert.IsNotNull(tmp.CurrentVersion);
            Assert.IsTrue(tmp.CurrentVersion.Value - expected < TimeSpan.FromSeconds(1));
            
            Assert.AreEqual(tmp.CurrentVersion, tmp.PublishFrom);
            Assert.IsNull(tmp.PublishTo);

            var tmpList = factory.GetAllVersions(tmp.NodeGuid).ToArray();
            Assert.AreEqual(existing + 1, tmpList.Count());

            ValidateProperties(tmp, tmpList[1]);

            var guids = _TestContentNodes.Where(x => x.ContentNodePositions.Count() > 1).GroupBy(x => x.NodeGuid).Select(x => x.Key);
            foreach (var guid in guids)
            {
                var tmp2 = factory.GetByNodeGuid(guid, tmp.CurrentVersion);
                if (_TestContentNodes.Where(x => x.NodeGuid == guid && x.ContentNodePositions.Count > 0).Count() > 0)
                {
                    Assert.IsNotNull(tmp2);
                    Assert.AreEqual(tmp.CurrentVersion, tmp2.CurrentVersion);
                }
                else
                {
                    Assert.IsNull(tmp2);
                }
            }
        }

        /*[TestMethod]
        public void ContentNode_Retire_NotAllVersions()
        {
            ContentNodeFactory factory = new ContentNodeFactory(_Context);
            var guid = _TestContentNodes[0].NodeGuid;
            var tmp = factory.GetByNodeGuid(guid, DateTime.Now);
            Assert.IsNotNull(tmp);
            factory.Retire(tmp, false);
            tmp = factory.GetByNodeGuid(_TestContentNodes[0].NodeGuid, DateTime.Now);
            Assert.IsNull(tmp);
        }*/
    }
}
